package com.vinjogames.entities;

import android.graphics.PointF;

import com.vinjogames.gfx.Image;
import com.vinjogames.util.GameConVars;
import com.vinjogames.util.LineSegmentF;
import com.vinjogames.util.Logger;
import com.vinjogames.util.Physics;
import com.vinjogames.util.VectorF;

/**
 * 
 * Projectile class for bullets, bombs, shells, and flying pigs.
 * 
 * @author Joey Jones
 *
 */
public class Projectile extends GameObject {
	
	//Types of projectiles:
	public static final int SHELL = 0; //Standard attack object for tank, artillery, cannon, and mortar.
	public static final int BOMB = 1; //Standard attack object for planes.
	public static final int MISSILE = 2; //Standard attack object for SAM battery, helicopter, and bazooka.
	public static final int FLAK = 3; //Standard attack for Flak cannon.
	public static final int BOUNCE = 5; //Standard attack for bouncey shells.
	public static final int MULTI = 6; //Standard attack for cluster cannon.
	public static final int FLAME = 7; //Standard attack for flamethrower cannon and fire-bomb.
	
	public static final int PIG = 50; //Standard attack for catapult.
	
	private static PointF tempPoint = new PointF();
	private static VectorF tempVector = new VectorF();
	private static LineSegmentF tempSegment = new LineSegmentF();
	
	private int attackType;
	private VectorF direction;
	private AttackObject firedBy;
	private PointF origin;
	private int pointsSpentOnAttack;
	private float damageDealt;
	private float minimumDamage;
	
	public Projectile() {
		firedBy = GameMap.World;
		direction = new VectorF();
		mLocation = new PointF();
		origin = mLocation;
		pointsSpentOnAttack = 1;
	}
	
	//TODO: Figure out how we're going to handle attack type.
	//Should attack objects set it for projectiles or should projectiles ask for it from objects?
	public Projectile(AttackObject obj, PointF loc, VectorF dir, int cost, float dmg) {
		mImage = new Image(GameConVars.GRAPHIC_PROJECTILES[0],.5f,.25f);
		firedBy = obj;
		mLocation = loc;
		origin = loc;
		direction = dir;
		pointsSpentOnAttack = cost;
		minimumDamage = GameConVars.UNIT_DAMAGE_MINIMUM_PERCENTAGE * (damageDealt = dmg);
	}

	public void initializeTo(AttackObject obj, PointF loc, VectorF dir, int cost, float dmg) {
		mImage = new Image(GameConVars.GRAPHIC_PROJECTILES[0],.5f,.25f);
		firedBy = obj;
		mLocation = loc;
		origin = loc;
		direction = dir;
		pointsSpentOnAttack = cost;
		minimumDamage = GameConVars.UNIT_DAMAGE_MINIMUM_PERCENTAGE * (damageDealt = dmg);
	}
	
	//Getters and setters.
	public int getAttackType() { return attackType; }
	public VectorF getDirection() {	return direction; }
	public void setDirection(VectorF direction) { this.direction = direction; }
	public AttackObject getFiredBy() { return firedBy; }

	/**
	 * 
	 * Find the location that a projectile will end up if it does not collide with anything.
	 * (Used for collision detection purposes)
	 * 
	 * @param time The change in time.
	 * @return A temporary point where the projectile would end up if it did not collide with anything.
	 */
	public VectorF getVectorToNewLocation(float time) {
		tempVector.setX(direction.getX() * time + Physics.WIND * time * time * 0.5f);
		tempVector.setY(direction.getY() * time + Physics.GRAVITY * time * time * 0.5f);
		return tempVector;
	}
	
	public PointF getNewLocation(float t) {
		tempPoint.x = origin.x + direction.getX() * t + Physics.WIND * t * t * 0.5f;
		tempPoint.y = origin.y + direction.getY() * t + Physics.GRAVITY * t * t * 0.5f;
		return tempPoint;
	}
		
	/**
	 * 
	 * Updates the location of the projectile based on the time value passed in.
	 * 
	 * @param t The change in time.
	 */
	public void updateLocation(float t) {
		mLocation.x = origin.x + direction.getX() * t + Physics.WIND * t * t * 0.5f;
		mLocation.y = origin.y + direction.getY() * t + Physics.GRAVITY * t * t * 0.5f;
		direction.setX(direction.getX() + Physics.WIND * t);
		direction.setY(direction.getY() + Physics.G * t);
		rotate((float) Math.toDegrees(Math.atan(direction.getY() / direction.getX())));
		Logger.log("Set projectile location at (" + mLocation.x + "," + mLocation.y + ")");
	}
	
	/**
	 * 
	 * Deal full damage to any object that was hit directly by a projectile.
	 * 
	 * @param obj The object that was struck
	 * 
	 */
/*	public void collidedWithDamageableObject(GameObject obj) {
		obj.takeDamage(this.damageDealt);
		Physics.getInstance().checkObjectDeath(obj);
	}*/
	
	/**
	 * 
	 * Deal damage to a GameObject that was hit by the blast radius of a projectile.
	 * 
	 * @param obj The object that was struck
	 * 
	 * @param poi The point of impact
	 * 
	 * @param distance The distance of the object from the blast radius
	 * 
	 */
	public void dealDamageToObject(GameObject obj, PointF poi, float distance) {
		float damage = damageDealt * (distance / firedBy.attackRadius);
		obj.takeDamage(damage > minimumDamage ? damage : minimumDamage);
		Physics.getInstance().checkObjectDeath(obj);
	}
	
/*	public void updateLocation(float t, VectorF v) {
		mLocation.x = mLocation.x + v.getX();
		mLocation.y = mLocation.y + v.getY();
		direction.setX(direction.getX() + Physics.WIND * t);
		direction.setY(direction.getY() + Physics.G * t);
	}
*/
	
	//TODO: Implement this.
	public void clearInfo() {
		
	}	
}
